#include "mycanvas.h"
#include "myinterpreter.h"

#include <GL/glut.h>

MyCanvas::MyCanvas(MyScene *_scene){
    this->scene = _scene;

    this->ctrl = false;
    
    this->modeling = new Modeling(this->scene);

    this->interpreter = new MyInterpreter();
    this->interpreter->setTraceFactory( new MyTraceFactory() );
    this->interpreter->setScene(this->scene);
    this->interpreter->setModeling(this->modeling);
}

void MyCanvas::onPressCursor(Cursor &cursor){
    Point scene_point = scene->getScenePoint(cursor);
    cursor.setScenePoint(scene_point);
    this->interpreter->addCursor(cursor);    
}

void MyCanvas::onMoveCursor(Cursor &cursor){
    Point scene_point = scene->getScenePoint(cursor);
    cursor.setScenePoint(scene_point);
    this->interpreter->addCursor(cursor);
}

void MyCanvas::onReleaseCursor(Cursor &cursor){
    Point scene_point = scene->getScenePoint(cursor);
    cursor.setScenePoint(scene_point);
    this->interpreter->addCursor(cursor);
    this->interpreter->finishTrace(cursor.getId());  
}

void MyCanvas::onPressKey(int key){

    switch(key){
        case KEY_CTRL:
            this->ctrl = true;
            break;
        case KEY_S:
            if (this->ctrl){
                saveImage();
            }
            break;
        case KEY_N:
            if (this->ctrl){
                traces.clear();
            }
            break;            
        case KEY_RIGHT:
            this->scene->setTranslateX( this->scene->getTranslateX()+0.5 );
            break;
        case KEY_LEFT:
            this->scene->setTranslateX( this->scene->getTranslateX()-0.5 );
            break;            

        case KEY_DOWN:
            if ( this->scene->getTranslateY() > -10.0)
                this->scene->setTranslateY( this->scene->getTranslateY()-0.5 );
                break;
        case KEY_UP:
            if ( this->scene->getTranslateY() < 35.0)
                this->scene->setTranslateY( this->scene->getTranslateY()+0.5 );
                break;        
            break;    
        case KEY_8:
            if (this->scene->getRotateX() < 0.0)
                this->scene->setRotateX( this->scene->getRotateX()+0.8 );
            break;
        case KEY_2:
            if (this->scene->getRotateX() > -85.0)
                this->scene->setRotateX( this->scene->getRotateX()-0.8 );
            break;
        case KEY_4:
                this->scene->setRotateY( this->scene->getRotateY()+0.8 );
            break;
        case KEY_6:
                this->scene->setRotateY( this->scene->getRotateY()-0.8 );
            break;
        case KEY_A:
            this->scene->setRotateX(0.0);
            this->scene->setRotateY(0.0);
            this->scene->setRotateZ(0.0);
            this->scene->setTranslateX(0.0);
            this->scene->setTranslateY(0.0);    
            break;
        case KEY_B:
            this->scene->setRotateX(-85.0);
            this->scene->setRotateY(0.0);
            this->scene->setRotateZ(0.0);        
            this->scene->setTranslateX(0.0);
            this->scene->setTranslateY(0.0);    
            break;
        case KEY_C:
            this->scene->setRotateX(-85.0);
            this->scene->setRotateY(90.0);
            this->scene->setRotateZ(0.0);        
            this->scene->setTranslateX(0.0);
            this->scene->setTranslateY(0.0);    
            break;
        case KEY_H:
            this->scene->disablePlane();   
            break;        
    }
    this->scene->updateEnviroment();
}


void MyCanvas::onReleaseKey(int key){
    if (key == KEY_CTRL) this->ctrl = false;
}


void MyCanvas::paint(void){
    scene->drawSegments();
    scene->drawPolygons();
    modeling->updateScene();
    glFlush();
}


void MyCanvas::initialize(){
    GLfloat  dimLight[] = { 0.1f, 0.1f, 0.1f, 1.0f };
    GLfloat  sourceLight[] = { 0.65f, 0.65f, 0.65f, 1.0f };
    GLfloat	 lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };

    glEnable(GL_DEPTH_TEST);

    glEnable(GL_LIGHTING);

    glLightfv(GL_LIGHT0, GL_AMBIENT, dimLight);
    glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight);
    glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
    glEnable(GL_LIGHT0);

    glEnable(GL_COLOR_MATERIAL);
    glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

    glClearColor(0.80f, 0.80f, 0.80f, 1.0f );
}


void MyCanvas::resizeCanvas(int _width, int _height){
    GLfloat fAspect;

    Viewport &viewport = this->scene->getViewport();
    Window &window = this->scene->getWindow();

    if (_width  == 0) _width  = 1;
    if (_height == 0) _height = 1;
    viewport.width = _width;
    viewport.height = _height;

    glViewport(viewport.left, viewport.top, viewport.width, viewport.height);

    fAspect = (GLfloat)_width/(GLfloat)_height;

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glOrtho(window.left, window.right, window.bottom, window.top, -10.0, 10.0);
    gluPerspective(20.0 , fAspect, -10.0, 30.0);
    gluLookAt(0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0);    

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}
